using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

namespace Linquid
{
	/// <summary>
	/// Collection of common UI actions
	/// </summary>
	public class UIM
	{	
		/// <summary>
		/// Produces an empty space used for layout.
		/// </summary>
		/// <param name="size">Minimal size of the empty space.</param>
		/// <param name="xStretch">Horizontal stretching priority.</param>
		/// <param name="yStretch">Vertical stretching priority.</param>
		/// <returns>UI action.</returns>
		public static UI<Nothing> EmptySpace(Size size, float xStretch, float yStretch)
		{
			return UI<int>.EmptySpace(size, xStretch, yStretch);
		}
		
		/// <summary>
		/// Generates an action that includes specific control in the layout.
		/// </summary>
		/// <param name="getControl">Function that creates a control given the font of the parent control.</param>
		/// <param name="getSource">Function that extracts source from the created control.</param>
		/// <param name="xStretch">Horizontal stretching priority.</param>
		/// <param name="yStretch">Vertical stretching priority.</param>
		/// <returns>UI action.</returns>
		public  static UI<Source<C>> Insert<B, C>(
			Func<Font, B> getControl, Func<B, Source<C>> getSource, float xStretch, float yStretch) 
			where B: Control
		{
			return UI<int>.Insert(getControl, getSource, xStretch, yStretch);
		}
		
		/// <summary>
		/// Produces an empty space of zero size.
		/// </summary>		
		/// <param name="xStretch">Horizontal stretching priority.</param>
		/// <param name="yStretch">Vertical stretching priority.</param>
		/// <returns>UI action</returns>
		public static UI<Nothing> EmptySpace(float xStretch, float yStretch)
		{
			return UI<int>.EmptySpace(Size.Empty, xStretch, yStretch);
		}
		
		/// <summary>
		/// Produces a button.
		/// </summary>
		/// <param name="caption">Caption of the button</param>
		/// <param name="xStretch">Horizontal stretching priority.</param>
		/// <param name="yStretch">Vertical stretching priority.</param>
		/// <returns>UI action.</returns>
		public static UI<Source<Nothing>> Button(string caption, float xStretch, float yStretch)
		{
			return UI<int>.Button(caption, xStretch, yStretch);
		}
		
		/// <summary>
		/// Produces a button.
		/// </summary>
		/// <param name="caption">Caption of the button</param>
		/// <returns>UI action.</returns>
		public static UI<Source<Nothing>> Button(string caption)
		{
			return UI<int>.Button(caption, 1.0f, 1.0f);
		}
		
		/// <summary>
		/// Produces a track bar.
		/// </summary>		
		/// <param name="min">Minimal value of the slider.</param>
		/// <param name="max">Maximal value of the slider.</param>
		/// <returns>UI action.</returns>		
		public static UI<Source<int>> Slider(int min, int max)
		{
			return UI<int>.Slider(min, max);
		}

		/// <summary>
		/// Produces a text input that generates string values.
		/// </summary>
		/// <returns>UI action.</returns>
		public static UI<Source<string>> Input()
		{
			return UI<int>.Input(s => s, "", 0.0f);
		}
		
		/// <summary>
		/// Produces a text input.
		/// </summary>
		/// <param name="init">Initial text of the input.</param>
		/// <param name="parse">Function that returns values of required type.</param>
		/// <returns>UI action.</returns>
		public static UI<Source<A>> Input<A>(string init, Func<string, A> parse)
		{
			return UI<int>.Input(parse, init, 0.0f);
		}
		
		/// <summary>
		/// Produces a text input.
		/// </summary>
		/// <param name="init">Initial text of the input.</param>
		/// <param name="parse">Function that returns values of required type.</param>
		/// <param name="stretch">Horizontal stretching priority.</param>
		/// <returns>UI action.</returns>				
		public static UI<Source<A>> Input<A>(string init, Func<string, A> parse, float stretch)
		{
			return UI<int>.Input(parse, init, stretch);
		}
		
		/// <summary>
		/// Produces a text input.
		/// </summary>
		/// <param name="init">Initial text of the input.</param>		
		/// <param name="stretch">Horizontal stretching priority.</param>
		/// <returns>UI action.</returns>
		public static UI<Source<string>> Input<A>(string init, float stretch)
		{
			return UI<int>.Input(s => s, init, stretch);
		}
		
		/// <summary>
		/// Produces a text output.
		/// </summary>
		/// <param name="source">Source of values to display.</param>
		/// <param name="stretch">Horizontal stretching priority.</param>
		/// <returns>UI action.</returns>
		public static UI<Nothing> Output<A>(Source<A> source, float stretch)
		{
			return UI<int>.Output(source, stretch);
		}
		
		/// <summary>
		/// Produces a text output.
		/// </summary>
		/// <param name="source">Source of values to display.</param>		
		/// <returns>UI action.</returns>
		public static UI<Nothing> Output<A>(Source<A> source)
		{
			return UI<int>.Output(source, 0.0f);
		}
		
		/// <summary>
		/// Produces a combo box.
		/// </summary>
		/// <param name="defaultChoice">Value that is selected initially.</param>
		/// <param name="choices">Items of the combo box.</param>
		/// <returns>UI action.</returns>
		public static UI<Source<A>> Choice<A>(A defaultChoice, params A[] choices)
		{
			return UI<int>.Choice(defaultChoice, choices);
		}
		
		/// <summary>
		/// Produces a combo box.
		/// </summary>
		/// <param name="defaultChoice">Value that is selected initially.</param>
		/// <param name="choices">Items of the combo box.</param>
		/// <returns>UI action.</returns>
		public static UI<Source<A>> Choice<A>(A defaultChoice, List<A> choices)
		{
			return UI<int>.Choice(defaultChoice, choices.ToArray());
		}
	}				
}